package com.lksoft.bz;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.LinkedHashMap;

/**
 * Serializer for StitchPattern object
 * 
 * @author Lake
 *
 */
public class StitchPatternSerializer {
	/** STPL header string */
	private static final String STPL_HEADER = "STPLv0.02";
	
	/** Extension 0.01: STP */
	public static final String STP_EXT = ".stp";
	/** Extension >0.02: STPL */
	public static final String STPL_EXT = ".stpl";
	
	
	/** Current save file extension () */
	public static final String SFILE_EXT = STPL_EXT;


	/**
	 * Write a stitch pattern in the lastest format
	 * @param file
	 * @return
	 */
	public static boolean writeStitchPattern(File file, StitchPattern pattern){
		return writeSTPL(file, pattern);
	}

	/**
	 * STPL形式を書き込む
	 * @param file Output file
	 * @param pattern The pattern
	 */
	private static boolean writeSTPL(File file, StitchPattern pattern) {
		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) {
			oos.writeUTF(STPL_HEADER);
			oos.writeInt(pattern.width);
			oos.writeInt(pattern.height);
			for( int w = 0; w<pattern.width; w++ ){
				for( int h=0; h<pattern.height; h++ ){
					oos.writeInt(pattern.pattern[w][h]);
				}
			}
			
			// Other fields normally
			oos.writeObject(pattern.stitchType);
			oos.writeObject(pattern.usedBeads);
			oos.writeObject(pattern.usedBeadsPool);
			
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * Read from file (supports old formats up to last deprecated)
	 * 
	 * @param file The stitch pattern file
	 * @return
	 */
	public static StitchPattern readStitchPattern(File file){
		// First try reading stp format (To be deprecated from version 0.03)
		StitchPattern pattern = readSTP(file);
		if( pattern != null ) return pattern;
		
		// If failed, read stpl
		pattern = readSTPL(file);
		return pattern;
	}

	/**
	 * Read stitch pattern in STPL format
	 * 
	 * @param file The file
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private static StitchPattern readSTPL(File file) {
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
			// New format: custom serialziation
			StitchPattern pattern = new StitchPattern();
			
			// Read version header
			String version = ois.readUTF();
			if( !version.equals(STPL_HEADER) ) return null;
			
			pattern.width = ois.readInt();
			pattern.height = ois.readInt();
			for( int w = 0; w<pattern.width; w++ ){
				for( int h=0; h<pattern.height; h++ ){
					pattern.pattern[w][h] = ois.readInt();
				}
			}
			
			// Other fields normally
			pattern.stitchType = (StitchType) ois.readObject();
			pattern.usedBeads = (LinkedHashMap<Integer, BeadUsage>) ois.readObject();
			pattern.usedBeadsPool = (LinkedHashMap<Integer, BeadUsage>) ois.readObject();
			
			return pattern;
		} catch (IOException | ClassNotFoundException e1) {
			return null;
		}
	}

	/**
	 * Read stitch pattern in STP format
	 * 
	 * @param file The file
	 * @return
	 */
	private static StitchPattern readSTP(File file) {
		try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
			return (StitchPattern) ois.readObject();
		} catch (IOException | ClassNotFoundException e1) {
			return null;
		}
	}
	
}
